#include "sprite.h"


CSprite::CSprite ()
{
  // por defecto
  visible=true;
  animstart=0;animspeed=0;animcount=0;animpos=0;
  x=0;
  y=0;
  w=0;
  h=0;
  rotacionZ = 0.0;escala = 1.0;filtro=1;
  usaalpha=true;     // por defecto usa alpha
  alpha = 255; // por defecto opaco
}

void CSprite::createxturas (char fname[128])
{
  FILE *fichero; 
  /* cargamos la infomacion de la capa */ 
  ifstream FSdata(fname,ios::in | ios::binary);              // Definimos Flayer como control de Fstream.
  FSdata.read(reinterpret_cast<char *>(&sdata),sizeof(sdata));      // leemos el stream en nuestro array de estructuras
  FSdata.close(); // cierra el fichero.   
  nsprite = sdata.spl * sdata.lines; // numero total de sprites.
  if (sdata.w>0 && sdata.h>0 ) printf ("CSprite::createxturas:: Sprite %s data loaded, %i sprites\n",fname,nsprite);
   else 
        {
          printf ("CSprite::createxturas:: Error!, Sprite data not loaded.\n");
          return;
          }
  w=sdata.w; // fijamos las dimensiones a las variables publicas para consulta.
  h=sdata.h; 
  rect.w=int(w*escala);
  rect.h=int(h*escala);
  printf ("CSprite::Csprite:%s , ancho:%i ,alto:%i\n",fname,sdata.w,sdata.h);
  char path[128]="sprites/";  // directorio
  strcat (path,sdata.sn);     // fija el directorio
  /* carga la textura */    
  sprite = IMG_Load(path);                         // carga el sprite
  if (sprite == NULL) printf ("Sprites::createxturas::Error al cargar sprite: %s img_err#%s\n",path,IMG_GetError());
     else printf ("Sprites::createxturas::Cargado sprite: %s de :%ix%i pixels\n",path,sdata.w,sdata.h);
  if (usaalpha) 
    {
     SDL_SetColorKey( sprite, SDL_SRCCOLORKEY, SDL_MapRGB(sprite->format, 255, 0, 255) ); // fija el color trasnparente para el alpha
     SDL_SetAlpha(sprite, SDL_SRCALPHA, alpha);                                    // fija el nivel de trasnparanecia 255 opaco , 0 transparente
     }
   
  sprite_array =new GLuint[nsprite];                 // crea el array de texturas
  textura=Crea_Imagen_Alpha1 ( sdata.w, sdata.h );
  SDL_Rect text_rect = {0,0,sdata.w,sdata.h};
  SDL_Rect anim_rect ={0,0,sdata.w,sdata.h};
  int control,posv,posh; // variables para calcular la posion de los sprites.
  for (int i=0;i<nsprite;i++)
      {
        SDL_FillRect(textura, NULL, 0x00000000);                                 // borra la textura cada vez que la aztualiza.
       
        //anim_rect.x =i*ancho; 
        /**************************************************************************/   
        /* Esta rutina calcula la posicion de cada tile dentro de la imagen de los tiles */
        /**************************************************************************/
        control = (sprite->w/sdata.w);               // halla el numero de tiles en un linea (ancho de la imagen entre el ancho del sprite)
        if (i>=control) posv=i / control;         // halla la posicion vertical,
         else posv=0;
        if (i>=control) posh  = i-control*posv;   // halla la posicion horizontal.
         else posh = i;
        /*************************************************************************/
        anim_rect.x=posh*sdata.w;
        anim_rect.y=posv*sdata.h;
        SDL_BlitSurface (sprite,&anim_rect,textura,&text_rect);
        glGenTextures (1, &textid);
        glBindTexture (GL_TEXTURE_2D , textid);
        glTexImage2D (GL_TEXTURE_2D, 0 ,4,textura->w,textura->h,0, GL_RGBA,GL_UNSIGNED_BYTE, textura->pixels );  //carga la textura en la memoria de video
        sprite_array[i]=textid;
     } 
  printf ("Srpite::Createxturas::Numero de texteturas:%i\n",nsprite);   
 //printf ("Srpite::Createxturas::id del priemro:%i id del ultimo:%i\n", sprite_array[0], sprite_array[nsprite-1]);   
 SDL_FreeSurface(sprite);                                                     // liberamos la memoria de las usperficies   
 SDL_FreeSurface(textura);                                                    // usadas.
}

void CSprite::pinta()
{
  rect.x=int(x - ( (rect.w-w) / 2 ) ); // calcula las dimensiones segun la escala
  rect.y=int(y - ( (rect.w-w) / 2 ) );
  if (visible==false) return; // nuevo
  int nancho=(sdata.w/2);    // nuevo
  int nalto = (sdata.h/2);    // nuevo
  int Ix = int (x)+nancho; // nuevo
  int Iy = int (y)+nalto;  // nuevo
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D,sprite_array[int(animpos)]);
  switch (filtro)
   {
    case 0: glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST );   // SIN FILTRO
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);    // SIN FILTRO
            break;
    case 1: glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR );
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR );
            break;
    case 2: glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT);   
            break;
   } 
 
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // a ver
  glTranslatef ( Ix, Iy, 0 );                                                   // Mueve el objeto
  glScalef (escala,escala,escala);                                              // produce el escalado
  glRotated (rotacionZ,0,0,1);                                                  // rota sobre el eje z
  glRotated (rotacionX,0,1,0);
  glRotated (rotacionY,0,0,1);
  glBegin (GL_QUADS);                                                         // Usamos el objeto Quads
    glTexCoord2d (1.0 , 0.0);
    //glTexCoord2d (0.0 , 0.0);                                                   //INVERTIDA
    //glVertex3f (0,0,0);
     glVertex3f (nancho,-nalto,0);
    
      glTexCoord2d (0.0 , 0.0);
    //glTexCoord2d (1.0 , 0.0);                                                   // invertida
    //glVertex3f (ancho,0   ,0);
     glVertex3f (-nancho,-nalto   ,0);
     
    glTexCoord2d (0.0 , 1.0);            
 //    glTexCoord2d (1.0 ,1.0);                                                    // normal
    //glVertex3f (ancho,alto,0);
     glVertex3f (-nancho,nalto,0);
    
     glTexCoord2d (1.0 , 1.0);
//    glTexCoord2d (0.0 , 1.0);                                                   // normal
    //glVertex3f (0    ,alto,0);    
     glVertex3f (nancho    ,nalto,0);    
  glEnd();                                                                    // fin
  glDisable(GL_BLEND); 
}

void  CSprite::ppcolision(int x,int y)
{
      /* reseta las variables de colisionm */
      colision=false;
      colderecha=false;
      colizquierda=false;
      colarriba=false;
      colabajo=false;
      
      /* variables de posicion para los calculos */
      int x1,y1;                                                                // nuevas variables para los calculos
      //for (int z=0;z<nsprite;z++)
      for (int i=0;i<(colpoints*2);i+=2)                                        // la matriz se comporta como byes para la posicion
      {                                                                         // pero lee int16
        x1,y1=0;                                                                // nota: solo funciona con los colpoints del sprite 0
        
        x1=x+Acolpoints[i];                                                     // calcula x + colpoints.x
        y1=y+Acolpoints[i+1];                                                   // calcula y + colpoints.y
        
        if (Coge_Pixel_Color_RGB( ppscreen, x1, y1 )>0)                         // controla el punto en las coordenadas indicadas
         {
          colision=true;
          /* datos para posicion de puntos de colision */
          switch (i)
          {
           case  0: colarriba=true;break;                                        // los cuatro primeros puntos marcanlas posiciones
           case  2: colarriba=true;break;
           case  4: colderecha=true;break;
           case  6: colderecha=true;break;
           case  8: colabajo=true;break;
           case 10: colabajo=true;break;
           case 12: colizquierda=true;break;                                     // definir en sentido contrario a las agujas del reloj
           case 14: colizquierda=true;break;                                     //  : 12h , 9h , 6h , 3h
         }
        }
      }
}

void CSprite::anima ()
{
  float speed=(float)animspeed / 1000;
  
  if (animpos<=(animstart+animcount)) animpos=animpos+speed;
  if (animpos>=(animstart+animcount)) animpos=animstart;
}

bool CSprite::colbox (SDL_Rect *spritea,SDL_Rect *spriteb)
{
  if (spritea->x + spritea->w < spriteb->x) return false;
  if (spritea->x > spriteb->x +spriteb->w) return false;

  if (spritea->y + spritea->h< spriteb->y)  return false;
  if (spritea->y > spriteb->y + spriteb->h) return false;
  return true;
}

bool CSprite::collision(SDL_Rect *spritea)
{
  if (spritea->x + spritea->w < x) return false;
  if (spritea->x > x          + w) return false;

  if (spritea->y + spritea->h < y)  return false;
  if (spritea->y >          y + h) return false;
  return true;
}    

bool CSprite::colboxc (float x,float y,int w,int h , float x1,float y1,int w1,int h1)
{
  if (x + w < x1) return false;
  if (x > x1 + w1) return false;

  if (y + h< y1)  return false;
  if (y > y1 + h1) return false;
  return true;
}


void CSprite::termina ()
{
   int i;
   for (i=0;i<nsprite;i++);
    {
     textid=sprite_array[i];
     glDeleteTextures ( 1, &textid );                                           // se borran todas las texturas.
     }
     delete [] Acolpoints;
     Acolpoints=NULL;
}

